const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
  constructor(excute) {
    // excute 参数是resolve和 reject
    this.state = "";
    this.value = "";
    this.reason = "";

    this.onFulfilledFns = [];
    this.onRejectedFns = [];

    const resolve = (value) => {
      if (this.state === PENDING) {
        queueMicrotask(() => {
          this.state = FULFILLED;
          this.value = value;
          this.onFulfilledFns.forEach((f) => {
            f(value);
          });
        });
      }
    };

    const reject = (reason) => {
      if (this.state === PENDING) {
        queueMicrotask((reason) => {
          this.state = REJECTED;
          this.reason = reason;
          this.onRejectedFns.forEach((f) => f(reason));
        });
      }
    };

    try {
      excute(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  /**
   *
   * @param {*} onFulfilled
   * @param {*} onRejected
   */
  then(onFulfilled, onRejected) {
    let promise;
    let x;
    // fulfilled状态了
    if (this.state === FULFILLED) {
      promise = new MyPromise((resolve, reject) => {
        try {
          setTimeout(() => {
            x = onFulfilled(this.value);
            resolvePromise(promise, x, resolve, reject);
          }, 0);
        } catch (reason) {
          reject(reason);
        }
      });
    } else if (this.state === REJECTED) {
      promise = new MyPromise((resolve, reject) => {
        try {
          setTimeout(() => {
            x = onRejected(this.reason);
            resolvePromise(promise, x, resolve, reject);
          }, 0);
        } catch (reason) {
          reject(reason);
        }
      });
    } else if (this.state === PENDING) {
      promise = new MyPromise((resolve, reject) => {
        this.onFulfilledFns.push(() => {
          try {
            setTimeout(() => {
              x = onFulfilled(this.value);
              resolvePromise(promise, x, resolve, reject);
            }, 0);
          } catch (reason) {
            reject(reason);
          }
        });

        this.onRejectedFns.push(() => {
          try {
            setTimeout(() => {
              x = onRejected(this.reason);
              resolvePromise(promise, x, resolve, reject);
            }, 0);
          } catch (reason) {
            reject(reason);
          }
        });
      });
    }

    return promise;
  }
}

function resolvePromise(promise, x, resolve, reject) {
  if (promise === x) {
    throw new Error(
      "fullFilled方法返回的对象不能是自身，不然一直是pengding状态，会卡死"
    );
  }
  // 递归一下处理
  if (x instanceof MyPromise) {
    x.then(
      (y) => {
        resolvePromise(promise, y, resolve, reject);
      },
      (e) => {
        reject(e);
      }
    );
  } else if (x !== null && (typeof x === "function" || typeof x === "object")) {
    let then;
    let excuted = false;
    try {
      then = x.then;
      if (typeof then === "function") {
        then.call(
          x,
          (y) => {
            if (excuted) return;
            excuted = true;
            resolvePromise(promise, y, resolve, reject);
          },
          (e) => {
            if (excuted) return;
            excuted = true;
            reject(e);
          }
        );
      }
    } catch (err) {
      if (excuted) return;
      excuted = true;
      reject(err);
    }
  } else {
    resolve(x);
  }
}
